import { useControlController, useNamespace } from '@ibiz-template/vue3-util';
import { ref, defineComponent, PropType, VNode } from 'vue';
import {
  IDEToolbar,
  IDEToolbarItem,
  IDETBGroupItem,
  IDETBUIActionItem,
} from '@ibiz/model-core';
import {
  IControlProvider,
  IExtraButton,
  ToolbarController,
} from '@ibiz-template/runtime';
import { IBizExportExcel } from './export-excel/export-excel';
import './toolbar.scss';

const btnContent = (item: IDEToolbarItem): (string | VNode)[] => {
  const image = item.sysImage;
  const result = [];
  const ns = useNamespace('toolbar-item');
  if (item.showIcon && image) {
    result.push(
      <span class={ns.b('icon')}>
        <iBizIcon icon={image} />
      </span>,
    );
  }
  if (item.showCaption && item.caption) {
    result.push(<span class={ns.b('text')}>{item.caption}</span>);
  }
  return result;
};

// 计算系统样式表名称
const calcCssName = (item: IDETBGroupItem | IDETBUIActionItem) => {
  return item?.sysCss?.cssName;
};

export const ToolbarControl = defineComponent({
  name: 'IBizToolbarControl',
  props: {
    modelData: {
      type: Object as PropType<IDEToolbar>,
      required: true,
    },
    context: { type: Object as PropType<IContext>, required: true },
    params: { type: Object as PropType<IParams>, default: () => ({}) },
    provider: { type: Object as PropType<IControlProvider> },
    manualCalcButtonState: { type: Boolean, default: false },
  },
  setup() {
    const c = useControlController((...args) => new ToolbarController(...args));
    const ns = useNamespace(`control-${c.model.controlType!.toLowerCase()}`);

    const btnSize = ref('default');
    const toolbarStyle = (c.model as IDEToolbar).toolbarStyle?.toLowerCase();

    // 点击事件
    const handleClick = async (
      item: IDEToolbarItem,
      event: MouseEvent,
      params?: IData,
    ): Promise<void> => {
      await c.onItemClick(item, event, params);
    };

    const renderExtraButtons = (extraButtons: IExtraButton[]): VNode[] => {
      return extraButtons.map(button => {
        return (
          <div key={button.id} class={[ns.e('item')]}>
            <el-button
              title={button.tooltip}
              size={btnSize.value}
              onClick={(e: MouseEvent): Promise<void> => handleClick(button, e)}
            >
              {btnContent(button)}
            </el-button>
          </div>
        );
      });
    };

    const renderSubmenu = (item: IDETBGroupItem) => {
      const detoolbarItems = item.detoolbarItems || [];
      // 子项有一个loading状态，父项也应该呈现loading状态
      const ploading =
        detoolbarItems.findIndex(
          item2 => c.state.buttonsState[item2.id!].loading,
        ) !== -1;
      // 子项所有项都隐藏，父项也应该隐藏
      const pvisible =
        detoolbarItems.findIndex(item2 => {
          return c.state.buttonsState[item2.id!].visible === true;
        }) !== -1;
      if (!pvisible) {
        return null;
      }
      // 子项所有项都禁用，父项也应该禁用
      const pdisabled =
        detoolbarItems.findIndex(item2 => {
          return c.state.buttonsState[item2.id!].disabled === false;
        }) === -1;
      const groupButtonStyle = item.buttonStyle || '';
      return (
        <el-sub-menu
          class={[
            ns.b('submenu'),
            ns.em('item', groupButtonStyle.toLowerCase()),
            calcCssName(item),
          ]}
          index={item.id}
          title={item.tooltip}
          popper-class={[
            ns.b('submenu-popper'),
            ns.bm('submenu-popper', toolbarStyle),
            ns.em('submenu-popper', groupButtonStyle.toLowerCase()),
            ns.bm('submenu-popper', calcCssName(item)),
          ]}
        >
          {{
            default: () => {
              return detoolbarItems.map(item2 => {
                const actionId = (item2 as IDETBUIActionItem).uiactionId;
                const visible = c.state.buttonsState[item2.id!]?.visible;
                if (!visible) {
                  return null;
                }
                if (item2.itemType === 'SEPERATOR') {
                  return;
                }
                if (item2.itemType === 'RAWITEM') {
                  return (
                    <el-menu-item
                      index={`menuitem${item2.id}`}
                      title={item2.tooltip}
                    >
                      <iBizRawItem
                        rawItem={item2}
                        class={ns.b('submenu-rawitem')}
                      ></iBizRawItem>
                    </el-menu-item>
                  );
                }
                if (item2.itemType === 'DEUIACTION') {
                  const buttonType = (
                    item2 as IDETBUIActionItem
                  ).buttonStyle?.toLowerCase();
                  if (actionId === 'exportexcel') {
                    return (
                      <IBizExportExcel
                        class={[
                          ns.e('menu-exportexcel'),
                          ns.em('item', buttonType),
                          calcCssName(item2),
                        ]}
                        mode='menu'
                        item={item2}
                        btnContent={btnContent}
                        size={btnSize.value}
                        controller={c}
                        onExportExcel={(e: MouseEvent, data: IData): void => {
                          handleClick(item2, e, data);
                        }}
                      ></IBizExportExcel>
                    );
                  }
                  return (
                    <el-menu-item
                      class={[
                        ns.is(
                          'loading',
                          c.state.buttonsState[item2.id!].loading,
                        ),
                        ns.em('item', buttonType),
                        calcCssName(item2),
                      ]}
                      index={`menuitem${item2.id}`}
                      disabled={c.state.buttonsState[item2.id!].disabled}
                      title={item2.tooltip}
                      onClick={(e: MouseEvent): Promise<void> =>
                        handleClick(item2, e)
                      }
                    >
                      <el-button
                        loading={c.state.buttonsState[item2.id!].loading}
                      >
                        {btnContent(item2)}
                      </el-button>
                    </el-menu-item>
                  );
                }
                if (item2.itemType === 'ITEMS') {
                  return renderSubmenu(item2);
                }
                return null;
              });
            },
            title: () => {
              return (
                <el-button loading={ploading} disabled={pdisabled}>
                  {btnContent(item)}
                </el-button>
              );
            },
          }}
        </el-sub-menu>
      );
    };

    const renderToolbarItem = (item: IDEToolbarItem): VNode | null => {
      const itemId = item.id!;
      const visible = c.state.buttonsState[itemId]?.visible;
      if (!visible) {
        return null;
      }
      if (item.itemType === 'SEPERATOR') {
        return (
          <div key={itemId} class={[ns.e('item'), ns.e('item-separator')]}>
            |
          </div>
        );
      }
      if (item.itemType === 'RAWITEM') {
        return (
          <div key={itemId} class={[ns.e('item'), ns.e('item-rawitem')]}>
            <iBizRawItem rawItem={item}></iBizRawItem>
          </div>
        );
      }
      if (item.itemType === 'DEUIACTION') {
        const actionId = (item as IDETBUIActionItem).uiactionId;
        const buttonType = (
          item as IDETBUIActionItem
        ).buttonStyle?.toLowerCase();
        if (actionId === 'exportexcel') {
          return (
            <IBizExportExcel
              class={[
                ns.e('item'),
                ns.e('item-deuiaction'),
                ns.em('item', buttonType),
                calcCssName(item),
              ]}
              item={item}
              btnContent={btnContent}
              size={btnSize.value}
              controller={c}
              onExportExcel={(e: MouseEvent, data: IData): void => {
                handleClick(item, e, data);
              }}
            ></IBizExportExcel>
          );
        }
        return (
          <div
            key={itemId}
            class={[
              ns.e('item'),
              ns.e('item-deuiaction'),
              ns.em('item', buttonType),
              calcCssName(item),
              ns.is('loading', c.state.buttonsState[itemId].loading),
            ]}
          >
            <el-button
              title={item.tooltip}
              size={btnSize.value}
              text={Object.is(buttonType, 'inverse')}
              type={buttonType}
              loading={c.state.buttonsState[itemId].loading}
              disabled={c.state.buttonsState[itemId].disabled}
              onClick={(e: MouseEvent): Promise<void> => handleClick(item, e)}
            >
              {btnContent(item)}
            </el-button>
          </div>
        );
      }
      if (item.itemType === 'ITEMS') {
        const groupButtonStyle = (item as IDETBGroupItem).buttonStyle || '';
        return (
          <el-menu
            mode='horizontal'
            class={[
              ns.e('menu'),
              ns.em('menu', groupButtonStyle.toLowerCase()),
              calcCssName(item),
            ]}
            ellipsis={false}
            menu-trigger='hover'
          >
            {renderSubmenu(item)}
          </el-menu>
        );
      }
      return null;
    };

    return {
      c,
      btnSize,
      ns,
      toolbarStyle,
      handleClick,
      renderExtraButtons,
      renderToolbarItem,
    };
  },
  render() {
    const { state } = this.c;
    let content = null;
    if (state.isCreated) {
      content = [
        // 绘制最前方的额外按钮
        state.extraButtons.before?.length > 0 &&
          this.renderExtraButtons(state.extraButtons.before),
        this.modelData.detoolbarItems?.map((item, index) => {
          const toolbarItemNode = this.renderToolbarItem(item);
          // 绘制指定位置后的额外按钮
          if (state.extraButtons[index]?.length) {
            return [
              toolbarItemNode,
              this.renderExtraButtons(state.extraButtons[index]),
            ];
          }
          return toolbarItemNode;
        }),
        // 绘制最后方的额外按钮
        state.extraButtons.after?.length > 0 &&
          this.renderExtraButtons(state.extraButtons.after),
      ];
    }

    return (
      <iBizControlBase
        controller={this.c}
        class={[
          this.ns.m(state.viewMode.toLowerCase()),
          this.ns.m(this.toolbarStyle),
        ]}
      >
        {content}
      </iBizControlBase>
    );
  },
});
